package com.dream.libx264;

import android.app.appsearch.ReportSystemUsageRequest;

public class XH264Encoder {

    // Used to load the 'libx264' library on application startup.
    static {
        System.loadLibrary("libx264");
    }

    public static final byte NAL_UNKNOWN     = 0;
    public static final byte NAL_SLICE       = 1;
    public static final byte NAL_SLICE_DPA   = 2;
    public static final byte NAL_SLICE_DPB   = 3;
    public static final byte NAL_SLICE_DPC   = 4;
    public static final byte NAL_SLICE_IDR   = 5;    /* ref_idc != 0 */
    public static final byte NAL_SEI         = 6;    /* ref_idc == 0 */
    public static final byte NAL_SPS         = 7;
    public static final byte NAL_PPS         = 8;
    public static final byte NAL_AUD         = 9;
    public static final byte NAL_FILLER      = 12;

    private byte[] sps;
    private byte[] pps;

    public XH264Encoder() {}

    public XH264Encoder(int width, int height) {
        nativeHandle = initEncoder(width, height);
    }

    /**
     * 测试编码器是否可以正常创建及编码
     */
    public native boolean test();

    /**
     * 测试编码器将YUV文件编码为H264文件
     * @return
     */
    public native boolean test2();


    private long nativeHandle; // 用于存储C++中的编码器句柄
    private OnEncodedDataAvailableListener listener;

    public interface OnEncodedDataAvailableListener {
        void onFormat(byte[] sps,byte[] pps);
        void onEncodedDataAvailable(byte[] encodedData, long pts, boolean isIFrame);
    }

    public void setOnEncodedDataAvailableListener(OnEncodedDataAvailableListener listener) {
        this.listener = listener;
    }

    public void encodeFrame(byte[] yuvData, long pts) {
        encode(nativeHandle, yuvData, pts);
    }

    public void flushAndClose() {
        flushAndCloseEncoder(nativeHandle);
        nativeHandle = 0;
    }

    private native long initEncoder(int width, int height);
    private native void encode(long handle, byte[] yuvData, long pts);
    private native void flushAndCloseEncoder(long handle);

    /**
     * JNI会在解码后回调该函数
     * @param encodedData
     * @param pts
     * @param type
     */
    private void onEncodedDataAvailableCallback(byte[] encodedData,long pts,int type) {
        if (listener != null) {
            if (type == NAL_PPS){
                pps = encodedData;
                if (sps!= null){
                    listener.onFormat(sps,pps);
                }
            }else if (type == NAL_SPS){
                sps = encodedData;
                if (pps!= null){
                    listener.onFormat(sps,pps);
                }
            }else{
                listener.onEncodedDataAvailable(encodedData, pts,type == NAL_SLICE_IDR);
            }
        }
    }
}